/*
 * Matt Adams
 * TCSS 558 HW1
 * Fall 2013
 */
package server;

import java.io.IOException;
import java.util.Iterator;
import java.util.SortedSet;

import tools.CheckArgument;
import tools.Log;
import tools.WordList;

/**
 * 
 * @author Matt Adams
 */
public abstract class SpellingServer {
    
    /**
     * Port number used for server.
     */
    protected final int port;
    
    /**
     * Word list to check queried words against.
     */
    protected final WordList wordList;
    
    /**
     * Constructs SpellingServer object.
     * 
     * @param portFilenameArray Listing of port and filename.
     */
    public SpellingServer(final String[] portFilenameArray) {
        if (portFilenameArray.length != 2) {
            Log.err("Usage: java UDPSpellingServer <port> <word-list>");
            errorClose();
        }
        this.port = CheckArgument.isValidPort(portFilenameArray[0]);
        this.wordList = getWordList(portFilenameArray[1]);
    }
    
    /**
     * Runs server.
     */
    public void runServer() {
        Log.out("Initiating server on port: " + this.port);
        boolean serverActive = true;
        
        while(serverActive) {
            try {
                receiveAndSend();
            } catch (IOException e) {
                Log.err("IO error receiving from or sending to client: " + e);
            }
        }
    }
    
    /**
     * Abstract method to receive data and send a response from this server.
     */
    protected abstract void receiveAndSend() throws IOException;
    
    /**
     * Properly displays server response to query.
     * 
     * @param queriedWord Queried word.
     * @param numberOfWords Number of close words.
     * @param closeWords Set of close words.
     * @return Returns formatted string of close words.
     */
    public String displayQueryResponse(final String queriedWord, final int numberOfWords, final SortedSet<String> closeWords) {
        String closeWordString = null;
        if (numberOfWords < 0) {
            Log.out(queriedWord + " is spelled correctly.");
        } else if (numberOfWords == 0) {
            Log.out(queriedWord + " is spelled incorrectly. There are no suggestions.");
        } else {     
            final StringBuilder sb = new StringBuilder();
            final Iterator<String> itr = closeWords.iterator();
            int count = 1;
            while (itr.hasNext() && count <= numberOfWords) {
                final String closeWord = itr.next();
                sb.append(closeWord);
                sb.append(" ");
                count++;
            }
            closeWordString = sb.toString();
            Log.out(queriedWord + " is spelled incorrectly.");
            Log.out("There are " + numberOfWords + " suggested words: " + closeWordString);
        }
        return closeWordString;
    }
    
    /**
     * Closes server if error occurs.
     */
    public void errorClose() {
        Log.out("Server shutdown from error.");
        System.exit(1);
    }
    
    /**
     * Creates WordList from a specified file.
     * 
     * @param filename Name of file.
     * @return Returns WordList.
     */
    public WordList getWordList(final String filename) {
        WordList result = null;
        try {           
            result = new WordList(filename);
            Log.out("Word list generated from file: " + filename);
        } catch (IOException e) {
            Log.err("Error generating word list for server: " + e);
            errorClose();
        }
        return result;
    }
}
